//单片机编程
    一.裸机系统中
    1.轮询系统
    2.前后台系统(main函数里面的无线大循环我们称之为后台,中断我们称之为前台)
    二.多线程系统(即RTOS)


//RT-Thread中所有的数据结构都称为对象  每个对象都会对应一个结构体(称为该对象的控制块)
//容器就是一个数组		线程是rtt里面最基本的对象
//RT-Thread中的优先级越高其数字越小,反之
//线程就绪优先级组 就是一个32位的整型数，每一个位对应一个优先级(即这样最多32个优先级)
//线程优先级表(就绪列表)
//RT-Thread是一个  抢占式实时操作系统
//一个进程可以分为多个线程
//heap 堆(应该是new 出来的)的申请和释放工作由程序员控制(动态内存)
//stack 栈由操作系统自动分配释放(静态内存)

//阻塞延时 和 软件延时 了解一下
//RTT是先创建并执行main线程，然后在main线程中再创建并执行其它线程,其它线程都创建完成后最后继续执行main函数,main函数执行到最后会通过LR寄存器指定的链接地址退出
//在创建main线程的时候LR里面的内容是rt_thread_exit函数
//中断服务函数的优先级高于任何优先级的线程
//空闲线程钩子了解一下(1.不会挂起空闲线程 2.不应该陷入死循环，需要留出部分时间用于系统处理系统资源回收)
//空闲线程不允许出现阻塞情况(即不会被挂起)
//一般来说处理时间更短的线程优先级应设置的更高一些
//IPC即进程间通信(inter process communication) IPC应该是通过全局变量来进行通讯的


    /**
     * 中断锁(关中断)和互斥锁是不同的
     * 中断锁:连中断都给禁止了,更不用说线程切换了    // rt_hw_interrupt_disable()  rt_hw_interrupt_enable()
     * 同步锁:只是线程切换给禁止了,但中断还是可以响应的 //rt_enter_critical()   rt_exit_critical()  
     */

    /*消息队列 即是一种常用于线程间通信的数据结构。可以在线程与线程间,中断和线程间传递信息 其是一种异步的通讯方式*/

    /*互斥量又称互斥型信号量,是一种特殊的二值信号量，可以递归访问
      主要针对临界资源的保护*/

    /*互斥量的优先级继承机制 :暂时提高占有资源的低优先级线程的优先级，以避免正在使用的系统资源被更高优先级的线程抢占*/

    /*互斥量不能在中断服务函数中使用*/

    /*优先级翻转：高优先级线程无法运行而低优先级线程可以运行的现象称为 "优先级翻转"
      被提高优先级的线程会在交接资源的时候恢复其原有的优先级*/

    /*线程递归获取信号量时会发生主动挂起(最终形成死锁，即一般的二值信号量)*/

    /*只有已持有互斥量所有权的线程才能释放它*/

    /*RT-Thread的事件仅用于同步，不提供数据传输功能*/

    /*事件和信号量的不同点(注意是不同点)*/
    1.事件的发送操作是不可累计的,而信号量的释放动作是可累计的
    2.信号量只能识别单一同步动作，不能同时等待多个事件的同步

    rt_event_send函数和rt_mutex_release,rt_sem_release函数有的一比

    /*句柄==指针*/

    rt_tick

    /*rt-thread在线程初始化 或者 创建线程的时候默认将其内部的回调函数初始化为了 rt_thread_timeout*/
    /*也就是说rt_thread_delay()是基于硬件来实现的*/

    RT-Thread的第一部分我们是在systick中断服务函数中实现定时器的扫描是否超时(使用了硬件定时器的资源) rt_thread_delay()
    RT-Thread的第二部分我们是在定时器线程中扫描是否超时(使用的是软件定时器资源)

    /*几种IPC通讯方式*/

//消息队列


//信号量



//互斥量(需求也是有优先级的)



//事件



//邮箱: 邮箱(也是一种异步的通讯方式，每一封邮件只能容纳固定的4字节内容)，与消息队列类似
    相比于信号量与消息队列来说，其开销更低，效率更高

//内存管理  (caution:不要在中断服务函数中，分配或释放动态内存块)
策略:
    静态内存分配算法可以保证设备的可靠性，但耗费内存
:
    动态内存提高了内存的使用效率，但可靠性不行，有可能出现内存碎片
//一些安全型的嵌入式系统,通常不允许动态内存分配！
    在满足设计要求的前提下，系统越是简单就越安全！
    动态内存变静态内存

    struct rt_mempool 静态内存控制块		rt_mp_create()静态内存创建函数
    rt_mp_init()静态内存初始化函数
//rt_mp_create()函数是创建		rt_mp_init()函数是将已经存在的缓冲区初始化(顺带加工一下)

//这里的创建rt_mp_create()或初始化rt_mp_init()之后才是静态内存申请函数rt_mp_alloc()

    静态内存
    rt_mp_create()是创建一个内存池
    rt_mp_free()针对内存块		/*这个是重点*/
    rt_mp_delete()针对内存池
    rt_mp_alloc()在创建完内存池之后从其中申请

    当使用rt_mp_init()时就不用上述的rt_mp_create()和rt_mp_alloc()

    动态内存的典型开发场景		(要记住用户不可能完全利用到那么多内存，因为内存管理器也要用内存)
    1.初始化系统堆内存空间			rt_system_heap_init();
    2.申请任意大小的动态内存		rt_malloc();
    3.释放动态内存，回收系统内存，供下一次使用	rt_free();

    内存池是一种用于分配大量大小相同的小对象的技术  它可以极大的加快内存分配/释放的速度
    当一个内存池对象被创建时,内存池对象就被分配给了一个内存池控制块(参数包括:内存池名,内存缓冲区,内存块大小,块数以及一个等待线程队列)
    内存池一旦初始化完成,内部的内存块大小将不能再做调整

5/2 :
    称为5除以2(2除5)

//中断管理
    任何使用了操作系统的中断响应都不会比裸机快
    中断屏蔽函数进入临界段的时候，也需快进快出
    中断控制器也是一个外设

    head=rt_malloc(sizeof(rt_list_t));		//直接分配出来就是一个双向链表?
    node1=rt_malloc(sizeof(rt_list_t));
    rt_list_insert_after(head,node1);


看个各位的解答，我大致总结了一下，如有错请各位斧正：
1、启动代码里的Stack_Size是1024 Bytes,这个RAM空间是给函数调用（包括中断）保存上下文用的，是真正的“主栈”；如果再定义变量（包括数组），编译器会把地址分配在这1024 byte之外。
2、编译器是不知道有没有RTOS的，所以Stack_Size定义的空间肯定不是给RT-Thread线程用的，RT-Thread的线程栈通过定义一个数组获取RAM空间，这个空间肯定在Stack_Size定义的空间之外。
3、没有RTOS的情况下,只要保证函数调用的层次别太深，压栈别超过1024 bytes的容量就行。（其实如果所有的寄存器都保存，也不过几十个字节，不会有人真调用几十级吧，那程序就太乱了，实在不行就扩大Stack_Size，哈哈...）
4、有RTOS的情况下，Stack_Size空间在内核启动之前有用，内核调度启动之后，每个线程都有自己的栈，真正的硬件SP寄存器在不同的线程栈切换...
5、启动代码里的Heap_Size,这个RAM空间是给编译器自带的malloc准备的，其实在没有使用RTOS的情况下，动态内存管理必要性不大，完全可以设置成0.
6、在RT-Thread里，可以动态管理的RAM是：所有RAM空间 - Stack_Size空间 - Heap_Size空间 - 所有变量空间（包括线程栈，就是数组），其实就是：所有RAM空间 - 编译器固定分配的空间。在没有使用动态内存管理的系统，这部分RAM是永远也用不到的。
说道最后，我脑子又出现一个小疑问：假如定义一个指针，强制指向一个高地址，而这个地址又被rt_malloc分配了，那通过这个指针更改内容会把系统搞崩溃吗？